package com.yonyou.openapi.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yonyou.openapi.base.auth.TenantAuthProvider;
import com.yonyou.openapi.base.datacenter.DataCenterUrlProvider;
import com.yonyou.openapi.base.exception.BusinessException;
import com.yonyou.openapi.base.properties.OpenApiProperties;
import com.yonyou.openapi.base.response.OpenApiAccessToken;
import com.yonyou.openapi.base.response.OpenApiResponse;
import com.yonyou.openapi.base.utils.ReSubmitUtil;
import com.yonyou.openapi.base.http.RequestUtil;
import lombok.Getter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.http.client.methods.HttpPost;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @description: 开放平台接口调用工具类
 **/
@Slf4j
@Component
public class BaseOpenApi {

    private ObjectMapper objectMapper = new ObjectMapper();
    @Resource
    TenantAuthProvider tenantAuthProvider;
    @Resource
    @Getter
    OpenApiProperties properties;
    @Resource
    public DataCenterUrlProvider dataCenterUrlProvider;

    private static String baseFilePath = "src/main/resources/file/";

    @SneakyThrows
    public <T> T getUrlForEntity(String urlFragment, Map<String,String> params,Class<T> responseType) {
        return  RequestUtil.doGetUrl(buildTokenRequestUrl(urlFragment),params, responseType);
    }

    @SneakyThrows
    public <T> T getForEntity(String urlFragment, Map<String,String> params,Class<T> responseType) {
        return  RequestUtil.doGet(buildTokenRequestUrl(urlFragment),params, responseType);
    }

    @SneakyThrows
    public <T> T postForEntity(String urlFragment, Object params,Class<T> responseType) {
        return RequestUtil.doPost(buildTokenRequestUrl(urlFragment),params,responseType);
    }

    public <T> T postForEntityReSubmit(String urlFragment, Object params,Class<T> responseType) {
        ReSubmitUtil.resubmitCheckKey(params);
        return postForEntity(urlFragment, params,responseType);
    }


    public <T> T postForEntityReSubmit(String urlFragment, Object params,Class<T> responseType,String dateFormat) {
        ReSubmitUtil.resubmitCheckKey(params, dateFormat);
        return postForEntity(urlFragment, params,responseType);
    }




    @SneakyThrows
    public <T> T getData(OpenApiResponse<T> body){
        if (body == null) {
            throw new BusinessException("unexpected response null when request open api isv access token");
        }
        body.check();
        log.info(objectMapper.writeValueAsString(body));
        return body.getData();
    }

    protected String buildTokenRequestUrl(String urlFragment) {
        String host = dataCenterUrlProvider.buildBusinessUrl();
        Map<String,String> params = new HashMap<String, String>();
        params.put("access_token", getAccessToken().getAccessToken());
        String url = properties.concatParam(host+urlFragment,  properties.buildQueryString(params, false));
        log.info("用友开放平台接口请求:"+url);
        return url;
    }

    protected OpenApiAccessToken getAccessToken(){
        return tenantAuthProvider.buildTenantAuthToken();
    }

    protected Map<String,Object> dataMap(Object object){
        Map<String,Object> map = new HashMap<>();
        map.put("data",object);
        return  map;
    }


    public String file(String urlFragment,String filePath,Map<String,String> header) throws IOException {
        String  reqUrl = buildGetRequestUrl(urlFragment,header);
        String path = new ClassPathResource(baseFilePath+filePath).getPath();
        FileSystemResource fileSystemResource = new FileSystemResource(path);
        File file = fileSystemResource.getFile();
        return RequestUtil.doPostByFile(reqUrl,null,file,"files");
    }

    protected String buildGetRequestUrl(String urlFragment,Map<String,String> params){
        if(MapUtils.isEmpty(params)){
            return buildTokenRequestUrl(urlFragment);
        }
        return properties.concatURL(buildTokenRequestUrl(urlFragment), "&", properties.buildQueryString(params, false));
    }


}
